package ULHT.LIG2N1.RC.VO;

/**
 * Gestão de Escrita e Leitura de Ficheiros
 *
 * @author Administrador
 */
import ULHT.LIG2N1.RC.SERVER.ClientGameData;
import ULHT.LIG2N1.RC.SERVER.GameVariables;
import java.beans.XMLDecoder;
import java.beans.XMLEncoder;
import java.io.*;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Random;
import java.util.logging.Level;
import java.util.logging.Logger;

public class FileManage implements Serializable {

    private static String Questionsfilename = "Questions.xml"; //Default
    private static String whiteListFileName = "WhiteList.Data";
    private Random randomGenerator;

    public QuestionVO getRandomQuestion() throws FileNotFoundException {
        try {
            QuestionVO pergunta = new QuestionVO();
            ArrayList<QuestionVO> listaperguntas = importQuestionListfromXML();

            randomGenerator = new Random();
            int index = 10;

            index = randomGenerator.nextInt(listaperguntas.size());
            pergunta = listaperguntas.get(index);

            return pergunta;
        } catch (ArrayIndexOutOfBoundsException ex) {
            Logger.getLogger(FileManage.class.getName()).log(Level.SEVERE, null, ex);
        }
        return null;
    }

    public void setQuestionsfilename(String Questionsfilename) {
        this.Questionsfilename = Questionsfilename;
    }

    public String getQuestionsfilename() {
        return Questionsfilename;
    }

    public FileManage() {
    }

    public static void exportQuestionListToXML(ArrayList<QuestionVO> perguntas) {
        try {
            XMLEncoder encoder = new XMLEncoder(new BufferedOutputStream(new FileOutputStream(Questionsfilename)));

            //get an Iterator object for ArrayList using iterator() method.
            Iterator itr = perguntas.iterator();

            //use hasNext() and next() methods of Iterator to iterate through the elements
            while (itr.hasNext()) {
                encoder.writeObject(itr.next());
            }
            encoder.flush();
            encoder.close();
        } catch (FileNotFoundException ex) {
            Logger.getLogger(FileManage.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

    //Importa do XML para objectos o ficheiro das Questões
    public static ArrayList<QuestionVO> importQuestionListfromXML() throws FileNotFoundException {
        QuestionVO question = new QuestionVO();
        ArrayList<QuestionVO> perguntas = new ArrayList<>();

        XMLDecoder decoder = new XMLDecoder(new BufferedInputStream(new FileInputStream(Questionsfilename)));

        try {
            while (true) {
                perguntas.add((QuestionVO) decoder.readObject());
            }
        } catch (ArrayIndexOutOfBoundsException exception) {
        } finally {
            decoder.close();
        }
        return perguntas;
    }

    public static ArrayList DeserializeBlackList() {
        FileInputStream fis;
        ArrayList List = new ArrayList();

        try {
            fis = new FileInputStream("BlackList.xml");
            XMLDecoder xdec = new XMLDecoder(fis);

            //Read object.
            List = (ArrayList) xdec.readObject();

            xdec.close();
            fis.close();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return List;
    }

    public static ArrayList<String> readArrayListFromFile(String filename) throws FileNotFoundException, IOException {

        FileInputStream fis;
        ArrayList<String> List = new ArrayList();


        fis = new FileInputStream(filename);
        XMLDecoder xdec = new XMLDecoder(fis);

        //Read object.
        List = (ArrayList) xdec.readObject();

        xdec.close();
        fis.close();

        return List;
    }

    //Escreve Black List para Ficheiro
    public void writeBlackList(GameVariables gameVariables) throws FileNotFoundException, IOException {
        //Declarar HashMpap para receber hashmap do gamevariables
        HashMap<String, ClientGameData> BlackList = new HashMap<>();

        //Guarda os IPs Blacklist para mandar escrever no ficheiro
        ArrayList<String> BlackListFile = new ArrayList<>();

        //Obtem hashmap
        BlackList = gameVariables.getClients();

        //Iterar hashmap
        Iterator<ClientGameData> it = BlackList.values().iterator();
        while (it.hasNext()) {
            //Guarda Endereço IP para verificar
            ClientGameData clientGameData = it.next();

            //Obtem o ipAdress desta iteração
            String ipaddress = clientGameData.getIpAdress().toString();

            //Se o IP é BlackListed, adiciona ao Arraylist
            if (clientGameData.isBlacklisted()) {
                BlackListFile.add(ipaddress);
            }
        }

        //Caso o ArrayList BlackListFile não está vazio, escreve para XML!!
        if (!BlackListFile.isEmpty()) {
            //Escrever Efectivamente para o ficheiro XML
            FileOutputStream fos = new FileOutputStream("BlackList.xml");

            XMLEncoder xenc = new XMLEncoder(fos);
            xenc.writeObject(BlackListFile);

            xenc.close();
            fos.close();
        }
    }

    //Escreve White List para Ficheiro
    /*
     * public void writeWhiteList(GameVariables gameVariables) throws
     * FileNotFoundException, IOException { //Declarar HashMpap para receber
     * hashmap do gamevariables HashMap<String, ClientGameData> BlackList = new
     * HashMap<>();
     *
     * //Guarda os IPs Blacklist para mandar escrever no ficheiro
     * ArrayList<String> BlackListFile = new ArrayList<>();
     *
     * //Obtem hashmap BlackList = gameVariables.getClients();
     *
     * //Iterar hashmap Iterator<ClientGameData> it =
     * BlackList.values().iterator(); while (it.hasNext()) { //Guarda Endereço
     * IP para verificar ClientGameData clientGameData = it.next();
     *
     * //Obtem o ipAdress desta iteração String ipaddress =
     * clientGameData.getIpAdress().toString();
     *
     * //Se o IP é BlackListed, adiciona ao Arraylist if
     * (clientGameData.isBlacklisted()) { BlackListFile.add(ipaddress); } }
     *
     * //Caso o ArrayList BlackListFile não está vazio, escreve para XML!! if
     * (!BlackListFile.isEmpty()) { //Escrever Efectivamente para o ficheiro XML
     * FileOutputStream fos = new FileOutputStream("WhiteList.xml");
     *
     * XMLEncoder xenc = new XMLEncoder(fos); xenc.writeObject(BlackListFile);
     *
     * xenc.close(); fos.close(); } }
     */
    public void writeArrayListToFile(ArrayList<String> arrayList, String filename) throws FileNotFoundException, IOException {

        //Caso o ArrayList não está vazio, escreve para XML!!
        if (!arrayList.isEmpty()) {
            //Escrever Efectivamente para o ficheiro XML
            FileOutputStream fos = new FileOutputStream(filename);

            XMLEncoder xenc = new XMLEncoder(fos);
            xenc.writeObject(arrayList);

            xenc.close();
            fos.close();
        }
    }

    public void writeLongToFile(long longValue, String filename) throws FileNotFoundException, IOException {

        ArrayList<String> arrayList = new ArrayList<>();
        arrayList.add(String.valueOf(longValue));

        //Caso o ArrayList não está vazio, escreve para XML!!
        if (!arrayList.isEmpty()) {
            //Escrever Efectivamente para o ficheiro XML
            FileOutputStream fos = new FileOutputStream(filename);

            XMLEncoder xenc = new XMLEncoder(fos);
            xenc.writeObject(arrayList);

            xenc.close();
            fos.close();
        }
    }

    public long readLongFromFile(String filename) throws FileNotFoundException, IOException {

        FileInputStream fis;
        ArrayList<String> List = new ArrayList();

        long value = 0;

        try {
            fis = new FileInputStream(filename);
            XMLDecoder xdec = new XMLDecoder(fis);

            //Read object.
            List = (ArrayList) xdec.readObject();

            xdec.close();
            fis.close();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }

        return value;
    }

    public void writeGameLogToFile(GameLogVO gameLogVO, String filename) throws FileNotFoundException, IOException {

        ArrayList<GameLogVO> gameLogVOarr = new ArrayList<>();
        gameLogVOarr.add(gameLogVO);

        //Caso o ArrayList não está vazio, escreve para XML!!
        if (!gameLogVOarr.isEmpty()) {
            //Escrever Efectivamente para o ficheiro XML
            FileOutputStream fos = new FileOutputStream(gameLogVO.getFilename());

            XMLEncoder xenc = new XMLEncoder(fos);
            xenc.writeObject(gameLogVOarr);

            xenc.close();
            fos.close();
        }
    }

    public ArrayList<GameLogVO> readGameLogFromFile(String filename) throws FileNotFoundException {

        //Instanciar apenas para obter filename para log
        GameLogVO log = new GameLogVO();
        ArrayList<GameLogVO> logArr = new ArrayList<>();
        ArrayList<GameLogVO> logArrFinal = new ArrayList<>();
        XMLDecoder decoder = new XMLDecoder(new BufferedInputStream(new FileInputStream(log.getFilename())));

        logArr = (ArrayList<GameLogVO>) decoder.readObject();

        Iterator<GameLogVO> itr = logArr.iterator();
        while (itr.hasNext()) {
            logArrFinal.add(itr.next());

            decoder.close();
        }
        return logArrFinal;
    }

    public void writeQuestionLimitVoToFile(QuestionLimitVO questionLimitVO, String filename) throws FileNotFoundException, IOException {
        FileOutputStream fos = new FileOutputStream(filename);
        ObjectOutputStream oos = new ObjectOutputStream(fos);

        oos.writeObject(questionLimitVO);

        oos.flush();
        oos.close();
    }

    public QuestionLimitVO readQuestionLimitVoFromFile(String filename) throws IOException, ClassNotFoundException {
        QuestionLimitVO questionLimitVO = new QuestionLimitVO();
        FileInputStream fis = new FileInputStream(filename);
        ObjectInputStream ois = new ObjectInputStream(fis);

        questionLimitVO = (QuestionLimitVO) ois.readObject();
        ois.close();

        return questionLimitVO;
    }

    public void writeGameVariablesToFile(GameVariables gamevars, String filename) throws FileNotFoundException, IOException {
        FileOutputStream fos = new FileOutputStream(filename);
        ObjectOutputStream oos = new ObjectOutputStream(fos);

        oos.writeObject(gamevars);

        oos.flush();
        oos.close();
    }

    public GameVariables readGameVariablesToFile(String filename) throws IOException, ClassNotFoundException {
        GameVariables gamevars;
        FileInputStream fis = new FileInputStream(filename);
        ObjectInputStream ois = new ObjectInputStream(fis);

        gamevars = (GameVariables) ois.readObject();
        ois.close();

        return gamevars;
    }

    public static void main(String[] args) throws Exception {

        FileManage fileManage = new FileManage();

        /*
         * GameLogVO log = new GameLogVO(); ArrayList<GameLogVO> arr = new
         * ArrayList<>(); GameVariables gameVariables = new GameVariables();
         *
         * gameVariables.setCurrentLevel(2); gameVariables.setPlayable(true);
         * gameVariables.setHoraInicioProximoJogo(DateTime.now());
         *
         * log.setGameVariables(gameVariables);
         *
         *
         *
         * //fileManage.writeGameLogToFile(log, log.getFilename());
         *
         * arr = fileManage.readGameLogFromFile(log.getFilename());
         *
         * System.out.println("Log: " +
         * arr.get(0).getGameVariables().getStringHoraInicioProximoJogo());
         *
         *
         */
        WhitelistVO wl = new WhitelistVO();
        BlacklistVO b1 = new BlacklistVO();
        wl.addToWhitelist("127.0.0.1");
        b1.addToBlacklist("192.168.200.1");
        fileManage.writeArrayListToFile(wl.getWhitelist(), wl.getFilename());
        fileManage.writeArrayListToFile(b1.getBlacklist(), b1.getFilename());

    }

    public static void Delete(String fileName) {

        File f = new File(fileName);
        if (!f.exists()) {
            throw new IllegalArgumentException(
                    "Delete: ficheiro ou directorio inexistente: " + fileName);
        }

        if (!f.canWrite()) {
            throw new IllegalArgumentException("Delete: protegido contra escrita: "
                    + fileName);
        }

        if (f.isDirectory()) {
            String[] files = f.list();
            if (files.length > 0) {
                throw new IllegalArgumentException(
                        "Delete: directorio não esta vazio: " + fileName);
            }
        }
        boolean success = f.delete();
        if (!success) {
            throw new IllegalArgumentException("Delete: FALHOU");
        }
    }
}
